/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nanosn.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 *
 * @author selkhateeb
 */
public class FileUtility
{
    // <editor-fold defaultstate="collapsed" desc="Copy functions">
    public static void Copy(InputStream inputStram, OutputStream outputStream) throws IOException
    {
        byte[] buffer = new byte[4096];
        for (;;)
        {
            int nBytes = inputStram.read(buffer);
            if (nBytes <= 0)
            {
                break;
            }
            outputStream.write(buffer, 0, nBytes);
        }
        outputStream.flush();
        outputStream.close();
        inputStram.close();
    }

    public static void Copy(File source, File distination) throws FileNotFoundException, IOException
    {
        FileInputStream from = null;
        FileOutputStream to = null;
        try
        {
            from = new FileInputStream(source);
            to = new FileOutputStream(distination);
            byte[] buffer = new byte[4096];
            int bytesRead;

            while ((bytesRead = from.read(buffer)) != -1)
            {
                to.write(buffer, 0, bytesRead); // write
            }
        } finally
        {
            if (from != null)
            {
                try
                {
                    from.close();
                } catch (IOException e)
                {
                    ;
                }
            }
            if (to != null)
            {
                try
                {
                    to.close();
                } catch (IOException e)
                {
                    ;
                }
            }
        }
    }

    public static void Copy(String source, String distination) throws FileNotFoundException, IOException
    {
        File fromFile = new File(source);
        File toFile = new File(distination);
        FileUtility.Copy(fromFile, toFile);
    }

    /**
     * Copys files and intract with user to whether overwrites existing files
     * or not.
     * @param fromFileName source
     * @param toFileName destination
     * @throws java.io.IOException
     */
    public static void CopyInteractive(String fromFileName, String toFileName)
            throws IOException
    {
        File fromFile = new File(fromFileName);
        File toFile = new File(toFileName);

        if (!fromFile.exists())
        {
            throw new IOException("FileUtility: " + "no such source file: " + fromFileName);
        }
        if (!fromFile.isFile())
        {
            throw new IOException("FileUtility: " + "can't copy directory: " + fromFileName);
        }
        if (!fromFile.canRead())
        {
            throw new IOException("FileUtility: " + "source file is unreadable: " + fromFileName);
        }

        if (toFile.isDirectory())
        {
            toFile = new File(toFile, fromFile.getName());
        }

        if (toFile.exists())
        {
            if (!toFile.canWrite())
            {
                throw new IOException("FileUtility: " + "destination file is unwriteable: " + toFileName);
            }
            System.out.print("Overwrite existing file " + toFile.getName() + "? (Y/N): ");
            System.out.flush();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    System.in));
            String response = in.readLine();
            if (!response.equals("Y") && !response.equals("y"))
            {
                throw new IOException("FileUtility: " + "existing file was not overwritten.");
            }
        } else
        {
            String parent = toFile.getParent();
            if (parent == null)
            {
                parent = System.getProperty("user.dir");
            }
            File dir = new File(parent);
            if (!dir.exists())
            {
                throw new IOException("FileUtility: " + "destination directory doesn't exist: " + parent);
            }
            if (dir.isFile())
            {
                throw new IOException("FileUtility: " + "destination is not a directory: " + parent);
            }
            if (!dir.canWrite())
            {
                throw new IOException("FileUtility: " + "destination directory is unwriteable: " + parent);
            }
        }

        FileUtility.Copy(fromFile, toFile);
    }
// </editor-fold>

    
    // <editor-fold defaultstate="collapsed" desc="FileListing">
    /**
     * Recursively walk a directory tree and return a List of all
     * Files found; the List is sorted using File.compareTo().
     *
     * @param aStartingDir is a valid directory, which can be read.
     */
    static public List<File> getFileListing(
            File aStartingDir) throws FileNotFoundException
    {
        validateDirectory(aStartingDir);
        List<File> result = getFileListingNoSort(aStartingDir);
        Collections.sort(result);
        return result;
    }

    // PRIVATE //
    static private List<File> getFileListingNoSort(
            File aStartingDir) throws FileNotFoundException
    {
        List<File> result = new ArrayList<File>();
        File[] filesAndDirs = aStartingDir.listFiles();
        List<File> filesDirs = Arrays.asList(filesAndDirs);
        for (File file : filesDirs)
        {
            result.add(file); //always add, even if directory
            if (!file.isFile())
            {
                //must be a directory
                //recursive call!
                List<File> deeperList = getFileListingNoSort(file);
                result.addAll(deeperList);
            }
        }
        return result;
    }

    /**
     * Directory is valid if it exists, does not represent a file, and can be read.
     */
    static private void validateDirectory(
            File aDirectory) throws FileNotFoundException
    {
        if (aDirectory == null)
        {
            throw new IllegalArgumentException("Directory should not be null.");
        }
        if (!aDirectory.exists())
        {
            throw new FileNotFoundException("Directory does not exist: " + aDirectory);
        }
        if (!aDirectory.isDirectory())
        {
            throw new IllegalArgumentException("Is not a directory: " + aDirectory);
        }
        if (!aDirectory.canRead())
        {
            throw new IllegalArgumentException("Directory cannot be read: " + aDirectory);
        }
    }
    // </editor-fold>
}
